#include "Menu.h"
#include <iostream>
//additional includes
#include <fstream>                                                                                                                  /** MSH on A3 **/
#include "OtherMSH.h"                                                                                                               /** MSH on C1 **/
#include "ShowFindUpdateMSH.h"                                                                                                      /** MSH on S1 **/
#include "ShowFindUpdateCPO.h"


using namespace std;

Menu::Menu()
{
}

void Menu::display_main_menu() const
{
	cout << "Here is the MAIN MENU :" << endl;                                                                                      /** MSH on A3 **/
	cout << "Display Info (1)" << endl;                                                                                             /** MSH on A3 **/
	cout << "Import from a File (2)" << endl;                                                                                       /** MSH on A3 **/
	cout << "Show Queries (3)" << endl;                                                                                             /** MSH on A3 **/
	cout << "Find Queries (4)" << endl;                                                                                             /** MSH on A3 **/
	cout << "Update Queries (5)" << endl;                                                                                           /** MSH on A3 **/
	cout << "Exit (6)" << endl;                                                                                                     /** MSH on A3 **/
	cout << "Please enter your choise by choosing one of the numbers in the bracket!" << endl;                                      /** MSH on A3 **/
}

void Menu::display_info() const
{	/*
	Edited by : Achmad Giovani
	-> Adding info: team name & team members
	-> To solve PROBLEM A2
	*/
	/* No lines deleted */
	cout << "Here is the Info requested \n";//display Project Part I, team name and team members
	/* Lines added for team info: */
	cout << "Team Name : BLUE-JKL-8 \n";
	cout << "Members: \n";
	cout << "\t Christopher P. Ogg \n";
	cout << "\t Achmad Giovani \n";
	cout << "\t Michell Setyawati Handaka \n\n";
}

void Menu::read()
{
    //cout << "Read file name then read store data \n";                                                                             /** MSH on A3 **/
    readCatPrd();                                                                                                                   /** MSH on A3 **/
	readCartAndItems();
    readCustInfo();
}

/*
		By: Achmad Giovani
		Function for reading the Carts and Cart Items
	*/
void Menu::readCartAndItems(){
	//filename = carts.dat
	string filePath;
	ifstream thefile;

	cout << "Carts filepath : ";
	cin >> filePath;
	thefile.open((char*)filePath.c_str());

	  if (thefile.is_open())
	  {
			carts.clear();		//emptying the vector
			cart_items.clear();
		  int cart_n; //number of cart
		  int cart_id, cart_item_id, cust_id, date_y, date_m, date_d, prod_id, prod_qty; //temporary values

		  /*===========
		  Read Cart data
		  ============*/

		  thefile >> cart_n;
		  for (int i=0; i<cart_n; ++i){
			thefile >> cart_id >> cust_id >> date_y >> date_m >> date_d;
			//Cart cart_temp(cart_id, cust_id, Date(date_y,(Date::Month)date_m,date_d));
			carts.push_back(Cart(cart_id, cust_id, Date(date_y,(Date::Month)date_m,date_d))); 	//push into cart vector
		  }

		  //test
		/*
		  for (int i=0; i<carts.size()-1; i++){
			cout << carts.at(i).display();
			}
			*/



		  /*===========
		  Read Cart Items data
		  ============*/

		  int cart_item_n;
		  thefile >> cart_item_n;
		  for (int i=0; i<cart_item_n; ++i){
			thefile >> cart_item_id >> cart_id >> prod_id >> prod_qty;
			cart_items.push_back(Cart_item(cart_item_id, cart_id, prod_id, prod_qty)); 	//push into cart_items vector
		  }
		  /*
		  for (int i=0; i<cart_items.size()-1; i++){
			cout << cart_items.at(i).display();
			}*/
		cout << filePath << " imported succesfully" << endl;

		thefile.close();
	  }

  else cout << "Unable to open file";
}

void Menu::readCatPrd()                                                                                                             /** MSH on A3 **/
{                                                                                                                                   /** MSH on A3 **/
    string filePath;                                                                                                                /** MSH on A3 **/
    ifstream file;                                                                                                                  /** MSH on A3 **/

	cout << "Category and Product File Path : ";                                                                                    /** MSH on A3 **/
	cin >> filePath;                                                                                                                /** MSH on A3 **/

	file.open((char*)filePath.c_str());                                                                                             /** MSH on A3 **/
	if (! file) {                                                                                                                   /** MSH on A3 **/
	    throw new InvalidFile;                                                                                                      /** MSH on A3 **/
	} else {                                                                                                                        /** MSH on A3 **/
	    bool validData = true;                                                                                                      /** MSH on A3 **/
	    int catN;                                                                                                                   /** MSH on A3 **/

	    file >> catN;                                                                                                               /** MSH on A3 **/
	    if (! catN) {                                                                                                               /** MSH on A3 **/
	        throw new InvalidData;                                                                                                  /** MSH on A3 **/
	    } else {                                                                                                                    /** MSH on A3 **/
	        int* catID = (int*) malloc(catN * sizeof(int));                                                                                                        /** MSH on A3 **/
	        string* catName = (string*) malloc(catN * sizeof(string));                                                                                                   /** MSH on A3 **/

	        for (int i = 0; (i < catN) && validData; ++i) {                                                                         /** MSH on A3 **/
	            if (! ((file >> catID[i]) && (file >> catName[i]))) {                                                               /** MSH on A3 **/
	                validData = false;                                                                                              /** MSH on A3 **/
	            }                                                                                                                   /** MSH on A3 **/
	        }                                                                                                                       /** MSH on A3 **/

	        if (validData) {                                                                                                        /** MSH on A3 **/
	            int prdN;                                                                                                           /** MSH on A3 **/

                file >> prdN;                                                                                                       /** MSH on A3 **/
                if (! prdN) {                                                                                                       /** MSH on A3 **/
                    throw new InvalidData;                                                                                          /** MSH on A3 **/
                } else {                                                                                                            /** MSH on A3 **/
                    int* prdID = (int*) malloc(prdN * sizeof(int));
					int* prdCID = (int*) malloc(prdN * sizeof(int));
					string* prdName = (string*) malloc(prdN * sizeof(string));														/** MSH on A3 **/
					double* prdPrice = (double*) malloc(prdN * sizeof(double));                                                     /** MSH on A3 **/

                    for (int i = 0; (i < prdN) && validData; ++i) {                                                                 /** MSH on A3 **/
                        if (! ((file >> prdID[i]) && (file >> prdCID[i]) && (file >> prdName[i]) && (file >> prdPrice[i]))) {       /** MSH on A3 **/
                            validData = false;                                                                                      /** MSH on A3 **/
                        }                                                                                                           /** MSH on A3 **/
                    }                                                                                                               /** MSH on A3 **/

                    if (validData) {                                                                                                /** MSH on A3 **/
                        cats.clear();                                                                                               /** MSH on A3 **/
                        prods.clear();                                                                                              /** MSH on A3 **/

                        for (int i = 0; i < catN; ++i) {                                                                            /** MSH on A3 **/
                            cats.push_back(Category(catID[i], catName[i]));                                                         /** MSH on A3 **/
                        }                                                                                                           /** MSH on A3 **/
                        for (int i = 0; i < prdN; ++i) {                                                                            /** MSH on A3 **/
                            prods.push_back(Product(prdID[i], prdCID[i], prdName[i], prdPrice[i]));                                 /** MSH on A3 **/
                        }                                                                                                           /** MSH on A3 **/

                        cout << "import done" << endl;                                                                              /** MSH on A3 **/
                    } else {                                                                                                        /** MSH on A3 **/
                        throw new InvalidData;                                                                                      /** MSH on A3 **/
                    }                                                                                                               /** MSH on A3 **/
                }                                                                                                                   /** MSH on A3 **/
	        } else {                                                                                                                /** MSH on A3 **/
	            throw new InvalidData;                                                                                              /** MSH on A3 **/
	        }                                                                                                                       /** MSH on A3 **/
	    }                                                                                                                           /** MSH on A3 **/
	}                                                                                                                               /** MSH on A3 **/

#ifdef DEBUG                                                                                                                        /** MSH on A3 **/
    for (unsigned int i = 0; i < cats.size(); ++i) {                                                                                /** MSH on A3 **/
        cout << cats[i].display() << endl;                                                                                          /** MSH on A3 **/
    }                                                                                                                               /** MSH on A3 **/
    for (unsigned int i = 0; i < prods.size(); ++i) {                                                                               /** MSH on A3 **/
        cout << prods[i].display() << endl;                                                                                         /** MSH on A3 **/
    }                                                                                                                               /** MSH on A3 **/
#endif                                                                                                                              /** MSH on A3 **/

}                                                                                                                                   /** MSH on A3 **/

// CPO on A1
void Menu::readCustInfo()
{
    string filePath;
	int cust_n;
    ifstream file;

    cout<<"Customer Info Filepath : ";
    cin>>filePath;

    file.open((char*)filePath.c_str());
    if(file.is_open())
    {
		custs.clear();
        string cust, street;
        int id, build, zip;
        file >> cust_n;


		for (int i=0; i<cust_n; ++i){

            file>>id>>cust>>build>>street>>zip;
            custs.push_back(Customer(id, cust, Street_address(build, street, zip)));


        }

		cout << filePath << " imported succesfully" << endl;
		/*
		for(int i=0; i<custs.size(); ++i)
                cout<<custs.at(i).display()<<endl; */
		file.close();
    }
    else cout<<"Unable to open file";
}


void Menu::show() const
{
	/* AGV on S3 */

	cout << "Show Products sorted by price: \n\n";
	cout << ShowFindUpdateAGV::show(prods);																							/* AGV on S3 */
	//cout << "Show queries \n";



	cout << "list all categories sorted by category ID" << endl;                                                                    /** MSH on S1 **/
	ShowFindUpdateMSH::show(cats, prods);                                                                                           /** MSH on S1 **/


        // CPO on S2
     cout<<"\nShow all Customers sorted by name"<<endl;
     cout << ShowFindUpdateCPO::show(custs);

	 //list all product in a given cart
	 cout << OtherCPO::list(cart_items,prods);

}

void Menu::find() const
{
	/* AGV on S3 */
	//choose entity: category, product, or customer

	int in;

	cout << "Choose entity: product, customer, or category" << endl;
	cout << "======================" << endl;
	cout << "1. Product" << endl;
	cout << "2. Customer" << endl;
	cout << "3. Category" << endl;
	cout << "======================" << endl;
	cout << "Choose find() type : "; cin >> in;

	switch (in){
		case 1:
			findProduct();
			break;
		case 2:
			findCustomer();
			break;
		case 3:
			findCategory();
			break;
	}

}

void Menu::update()
{
	int in;

	cout << "Choose entity: category and product, customer, cart item, or cart" << endl;
	cout << "======================" << endl;
	cout << "1. Category and Product" << endl;
	cout << "2. Customer" << endl;
	cout << "3. Add Cart item" << endl;
	cout << "4. Add Cart" << endl;
	cout << "5. Delete Cart item" << endl;
	cout << "======================" << endl;
	cout << "Choose update() type : "; cin >> in;

	switch (in){
		case 1:
			updateCatPrd();
			break;
		case 2:
			updateCustomer();
			break;
		case 3:
			updateCartItem(1);
			break;
		case 4:
			updateCart();
			break;
		case 5:
			updateCartItem(2);
			break;
	}

}


void Menu::findProduct() const{
    cout << "list of existing products : " << endl;                                                                                 /** MSH on S1 **/
	for (unsigned int i = 0; i < prods.size(); ++i) {                                                                               /** MSH on S1 **/
        cout << prods[i].display() << endl;                                                                                         /** MSH on S1 **/
    }

	int prdID;                                                                                                                      /** MSH on S1 **/
	cout << "display total sales for a given product" << endl;                                                                      /** MSH on S1 **/
	cout << "product ID : ";                                                                                                        /** MSH on S1 **/
	cin >> prdID;                                                                                                                   /** MSH on S1 **/
	ShowFindUpdateMSH::find(prdID, prods, cart_items);                                                                              /** MSH on S1 **/
}

void Menu::findCustomer() const{
	// CPO on S2
        cout<<"Companies and id's"<<endl;

		//cout << custs.at(0).get_cust_name() << endl;

		for(int x=0;x<custs.size();x++)
        {
            cout<<custs.at(x).display()<<endl;
        }


        // CPO on S2
        int custid;
        cout<<"\nCompany ID : ";
        cin>>custid;
        cout <<"Total sales for Company" << custid << " is " << ShowFindUpdateCPO::find(custid, carts, cart_items, prods) << endl;
}

void Menu::findCategory() const{
	/* AGV on S3 */
	string cat_name;																												/* AGV on S3 */
	//display categories
	cout << "Categories: \n\n";																										/* AGV on S3 */
	for(int i=0; i < cats.size(); ++i){																								/* AGV on S3 */
		cout << cats.at(i).display() << endl;																						/* AGV on S3 */
	}

	cout << "\nCategory name : ";																									/* AGV on S3 */
	cin >> cat_name;																												/* AGV on S3 */
	cout << "Total sales for " << cat_name << " category: " << ShowFindUpdateAGV::find(cart_items, cats, prods, cat_name);			/* AGV on S3 */
	cout << "\n\n";

}


void Menu::updateCatPrd(){
	cout << "list of existing category : " << endl;                                                                                 /** MSH on S1 **/
	for (unsigned int i = 0; i < cats.size(); ++i) {                                                                                /** MSH on S1 **/
        cout << cats[i].display() << endl;                                                                                          /** MSH on S1 **/
    }

	cout << "list of existing products : " << endl;                                                                                 /** MSH on S1 **/
	for (unsigned int i = 0; i < prods.size(); ++i) {                                                                               /** MSH on S1 **/
        cout << prods[i].display() << endl;                                                                                         /** MSH on S1 **/
    }

    int opt;                                                                                                                        /** MSH on C1 **/
    cout << "Here is the OPTIONS :" << endl;                                                                                        /** MSH on C1 **/
    cout << "Add Category (1)" << endl;                                                                                             /** MSH on C1 **/
    cout << "Add Product (2)" << endl;                                                                                              /** MSH on C1 **/
    cout << "Edit Product (3)" << endl;                                                                                             /** MSH on C1 **/
    cout << "Delete Product (4)" << endl;                                                                                           /** MSH on C1 **/
    cout << "Please enter your choise by choosing one of the numbers in the bracket!" << endl;                                      /** MSH on C1 **/
    cin >> opt;                                                                                                                     /** MSH on C1 **/

    int catID, prdID, prdCID;                                                                                                       /** MSH on S1 **/
    string catName, prdName;                                                                                                        /** MSH on S1 **/
    double prdPrice;                                                                                                                /** MSH on S1 **/

    switch (opt) {                                                                                                                  /** MSH on C1 **/
        case 1 :                                                                                                                    /** MSH on C1 **/
            cout << "add a new category" << endl;                                                                                   /** MSH on C1 **/
            cout << "category ID : "; cin >> catID;                                                                                 /** MSH on S1 **/
            cout << "category name : "; cin >> catName;                                                                             /** MSH on S1 **/
            OtherMSH::add(catID, catName, cats);                                                                                    /** MSH on C1 **/
            break;                                                                                                                  /** MSH on C1 **/
        case 2 :                                                                                                                    /** MSH on C1 **/
            cout << "add a new product to an existing category" << endl;                                                            /** MSH on S1 **/
            cout << "product ID : "; cin >> prdID;                                                                                  /** MSH on S1 **/
            cout << "category ID : "; cin >> prdCID;                                                                                /** MSH on S1 **/
            cout << "product name : "; cin >> prdName;                                                                              /** MSH on S1 **/
            cout << "product price : "; cin >> prdPrice;                                                                            /** MSH on S1 **/
            ShowFindUpdateMSH::update(prdID, prdCID, prdName, prdPrice, cats, prods);                                               /** MSH on S1 **/
            break;                                                                                                                  /** MSH on C1 **/
        case 3 :                                                                                                                    /** MSH on C1 **/
            cout << "change the price of a given product" << endl;                                                                  /** MSH on C1 **/
            cout << "product ID : "; cin >> prdID;                                                                                  /** MSH on S1 **/
            cout << "product price : "; cin >> prdPrice;                                                                            /** MSH on S1 **/
            OtherMSH::edit(prdID, prdPrice, prods);                                                                                 /** MSH on C1 **/
            break;                                                                                                                  /** MSH on C1 **/
        case 4 :                                                                                                                    /** MSH on C1 **/
            cout << "delete a product from a category" << endl;                                                                     /** MSH on C1 **/
            cout << "category ID : "; cin >> catID;                                                                                 /** MSH on S1 **/
            OtherMSH::del(catID, cats, prods);                                                                                      /** MSH on C1 **/
            break;                                                                                                                  /** MSH on C1 **/
    }                                                                                                                               /** MSH on C1 **/
}

void Menu::updateCustomer(){
	// CPO on S2
        int custid, building, zip;
        string customer, street;
        cout<<"Add a new Customer"<<endl;
        cout<<"Customer ID : "; cin>>custid;
        cout<<"Customer Name : "; cin>>customer;
        cout<<"Building number : "; cin>>building;
        cout<<"Street Name : "; cin>>street;
        cout<<"Zip Code : "; cin>>zip;
        ShowFindUpdateCPO::update(Customer(custid, customer, Street_address(building, street, zip)), custs);
		/* print customers */
	for (int i=0; i<custs.size(); ++i){																						/* AGV on S3 */
		cout << custs.at(i).display();																							/* AGV on S3 */
	}
}

void Menu::updateCartItem(int opt){
	/* AGV on S3 */

	if (opt == 1){
		//add cart item
		int ciid, cid, pid, pqty; //temporary variables to store attribute values for the new Cart_item

		cout << "-New Cart item to be added-\n";																						/* AGV on S3 */
		cout << "Cart item ID: "; 	cin >> ciid;																						/* AGV on S3 */
		cout << "Cart ID: "; 		cin >> cid;																							/* AGV on S3 */
		cout << "Product ID: "; 	cin >> pid;																							/* AGV on S3 */
		cout << "Product qty: "; 	cin >> pqty;																						/* AGV on S3 */

		ShowFindUpdateAGV::update(Cart_item(ciid,cid,pid,pqty), carts, prods, cart_items);												/* AGV on S3 */

		for (int i=0; i<cart_items.size(); ++i){																						/* AGV on S3 */
			cout << cart_items.at(i).display();																							/* AGV on S3 */
		}																																/* AGV on S3 */
		//cout << "Update queries \n";
	}
	else if (opt == 2){
		//delete cart item
		int ciid;

		cout << "Cart item ID to be deleted: "; cin >> ciid;

		OtherCPO::remove(cart_items,ciid);
		cout << "\nCart item with ID " << ciid << " succesfully deleted" << endl;
	}

}

void Menu::updateCart(){

	int cid;
	string cname="";
	Street_address addr;
	int y,m,d;

	cout << "Customer ID : "; cin >> cid;

	//find customer name and Street_address given by ID
	for(int i=0; i<custs.size(); ++i){
		if (custs.at(i).get_cust_id() == cid){
			cname = custs.at(i).get_cust_name();
			addr = custs.at(i).get_cust_addr();
			break;
		}
	}

	cout << "Date (yyyy mm dd) : "; cin >> y >> m >> d;

	OtherCPO::addCart(carts, Customer(cid,cname,addr), Date(y, (Date::Month) m, d));
	cout << "\nCart succcesfully added" << endl;
}

void Menu::write(){
	OtherAGV::write(carts, cart_items, cats, prods, custs);																		/* AGV on C3 */
}

